/**
 * Copyright 2007-2010 非也
 * All rights reserved. 
 * 
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License v3 as published by the Free Software
 * Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
 *
 */
package org.fireflow2.designer.eclipse.modelwrapper.basic;

import java.util.List;

import org.fireflow.model.process.WorkflowElement;
import org.fireflow.pdl.fpdl20.diagram.ActivityShape;
import org.fireflow.pdl.fpdl20.diagram.CommentShape;
import org.fireflow.pdl.fpdl20.diagram.DiagramElement;
import org.fireflow.pdl.fpdl20.diagram.EndNodeShape;
import org.fireflow.pdl.fpdl20.diagram.Fpdl20DiagramElement;
import org.fireflow.pdl.fpdl20.diagram.GroupShape;
import org.fireflow.pdl.fpdl20.diagram.LaneShape;
import org.fireflow.pdl.fpdl20.diagram.RouterShape;
import org.fireflow.pdl.fpdl20.diagram.StartNodeShape;
import org.fireflow.pdl.fpdl20.diagram.WorkflowNodeShape;
import org.fireflow.pdl.fpdl20.process.Activity;
import org.fireflow.pdl.fpdl20.process.EndNode;
import org.fireflow.pdl.fpdl20.process.Router;
import org.fireflow.pdl.fpdl20.process.StartNode;
import org.fireflow.pdl.fpdl20.process.SubProcess;
import org.fireflow2.designer.eclipse.modelwrapper.ModelWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.NodeWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.SubProcessWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.Wrapper;

/**
 *
 * @author 非也 nychen2000@163.com
 * Fire Workflow 官方网站：www.firesoa.com 或者 www.fireflow.org
 *
 */
public class LaneWrapper extends NodeWrapper {

	/**
	 * @param parentWrapper
	 * @param arg0
	 * @param arg1
	 */
	public LaneWrapper(SubProcessWrapper subflowWrapper, 
			DiagramElement arg1) {
		super(subflowWrapper, null, arg1);
		initNodes();
	}

	protected void initNodes(){
		LaneShape laneShape = (LaneShape)this.getDiagramElement();
		SubProcess subflow = (SubProcess)this.subProcessWrapper.getWorkflowModelElement();
		
		List<WorkflowNodeShape> nodeShapeList = laneShape.getWorkflowNodeShapes();
		List<GroupShape> groupShapeList = laneShape.getGroups();
		List<CommentShape> commentShapeList = laneShape.getComments();

		if (groupShapeList!=null){
			for (GroupShape groupShape : groupShapeList){
				ModelWrapper modelWrapper = null;
				modelWrapper = new GroupWrapper(subProcessWrapper,groupShape);
	
				if (modelWrapper!=null){
					modelWrapper.setParent(this);
					this.getChildren().add(modelWrapper);
					subProcessWrapper.putToSnModelWrapperMap(modelWrapper.getSn(), modelWrapper);					

				}
			}
		}
		
		if (commentShapeList!=null){
			for (CommentShape commentShape : commentShapeList){
				ModelWrapper modelWrapper = null;
				modelWrapper = new CommentWrapper(subProcessWrapper,commentShape);
	
				if (modelWrapper!=null){
					modelWrapper.setParent(this);
					this.getChildren().add(modelWrapper);
					subProcessWrapper.putToSnModelWrapperMap(modelWrapper.getSn(), modelWrapper);					

				}
			}
		}
		
		if (nodeShapeList!=null){
			for (WorkflowNodeShape nodeShape : nodeShapeList){
				String wfElmID = nodeShape.getWorkflowElementRef();
				
				WorkflowElement wfElm = subflow.findWFElementById(wfElmID);
				ModelWrapper modelWrapper = null;
				if (nodeShape instanceof StartNodeShape){
					modelWrapper = new StartNodeWrapper(subProcessWrapper,(StartNode)wfElm,nodeShape);
					subProcessWrapper.getStartNodesWrapper().addChild((StartNodeWrapper)modelWrapper);
				}
				else if (nodeShape instanceof ActivityShape){
					modelWrapper = new ActivityWrapper(subProcessWrapper,(Activity)wfElm,nodeShape);
					subProcessWrapper.getActivitiesWrapper().addChild((ActivityWrapper)modelWrapper);
				}
				else if (nodeShape instanceof RouterShape){
					modelWrapper = new RouterWrapper(subProcessWrapper,(Router)wfElm,nodeShape);
					subProcessWrapper.getRoutersWrapper().addChild((RouterWrapper)modelWrapper);
				}
				else if (nodeShape instanceof EndNodeShape){
					modelWrapper = new EndNodeWrapper(subProcessWrapper,(EndNode)wfElm,nodeShape);
					subProcessWrapper.getEndNodesWrapper().addChild((EndNodeWrapper)modelWrapper);
				}

				if (modelWrapper!=null){
					modelWrapper.setParent(this);
					this.getChildren().add(modelWrapper);
					subProcessWrapper.putToSnModelWrapperMap(modelWrapper.getSn(), modelWrapper);					

				}

			}
		}
		

	}
	public void orphanChild(Wrapper child){
		LaneShape lane = (LaneShape)this.getDiagramElement();
		if (child instanceof GroupWrapper){
			lane.getGroups().remove(((NodeWrapper)child).getDiagramElement());
		}
		else if (child instanceof StartNodeWrapper ||
				child instanceof EndNodeWrapper ||
				child instanceof RouterWrapper ||
				child instanceof ActivityWrapper){
			lane.getWorkflowNodeShapes().remove(((NodeWrapper)child).getDiagramElement());
		}
		else if (child instanceof CommentWrapper){
			lane.getComments().remove(((NodeWrapper)child).getDiagramElement());
		}
		super.orphanChild(child);
	}
	
	public void acceptChild(Wrapper wrapper){
		if (!(wrapper instanceof NodeWrapper))return;
		NodeWrapper child = (NodeWrapper)wrapper;
		wrapper.setParent(this);
		LaneShape lanShape = (LaneShape)this.getDiagramElement();
		if (child instanceof GroupWrapper){
			lanShape.addGroup((GroupShape)child.getDiagramElement());
		}
		else if (child instanceof StartNodeWrapper ||
				child instanceof EndNodeWrapper ||
				child instanceof RouterWrapper ||
				child instanceof ActivityWrapper){
			lanShape.addWorkflowNodeShape((WorkflowNodeShape)child.getDiagramElement());
		}
		else if (child instanceof CommentWrapper){
			lanShape.addComment((CommentShape)child.getDiagramElement());
		}
		
		this.addChild(child,-1);
	}

	public void addChild(Wrapper child,int index){
		child.setParent(this);
		SubProcess subflow = (SubProcess)subProcessWrapper.getWorkflowModelElement();
		LaneShape laneShape = (LaneShape)this.getDiagramElement();
		
		if (child instanceof ActivityWrapper){
			Activity node = (Activity)((ActivityWrapper)child).getWorkflowModelElement();
			subflow.getActivities().add(node);
			laneShape.addWorkflowNodeShape((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
		
			subProcessWrapper.getActivitiesWrapper().addChild(child);
		}else if (child instanceof RouterWrapper){
			Router node = (Router)((RouterWrapper)child).getWorkflowModelElement();
			subflow.getRouters().add(node);
			laneShape.addWorkflowNodeShape((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getRoutersWrapper().addChild(child);
		}else if (child instanceof StartNodeWrapper){
			StartNode node = (StartNode)((StartNodeWrapper)child).getWorkflowModelElement();
			subflow.getStartNodes().add(node);
			laneShape.addWorkflowNodeShape((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getStartNodesWrapper().addChild(child);
		}else if (child instanceof EndNodeWrapper){
			EndNode node = (EndNode)((EndNodeWrapper)child).getWorkflowModelElement();
			subflow.getEndNodes().add(node);
			laneShape.addWorkflowNodeShape((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getEndNodesWrapper().addChild(child);
		}else if (child instanceof CommentWrapper){
			CommentShape elm = (CommentShape)((EndNodeWrapper)child).getDiagramElement();
			laneShape.addComment(elm);
		}else if (child instanceof GroupWrapper){
			GroupShape elm = (GroupShape)((GroupWrapper)child).getDiagramElement();
			laneShape.addGroup(elm);
		}else if (child instanceof ServiceDefWrapper){
			this.getParent().addChild(child,index);//交给subprocess wrapper处理。
		}
		subProcessWrapper.putToSnModelWrapperMap(child.getSn(), child);
		super.addChild(child,index);
	}
	
	public void deleteChild(ModelWrapper child){
		child.setParent(null);
		SubProcess subflow = (SubProcess)subProcessWrapper.getWorkflowModelElement();
		LaneShape laneShape = (LaneShape)this.getDiagramElement();
		
		if (child instanceof ActivityWrapper){
			Activity node = (Activity)((ActivityWrapper)child).getWorkflowModelElement();
			subflow.getActivities().remove(node);
			laneShape.getWorkflowNodeShapes().remove((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getActivitiesWrapper().deleteChild(child);
		}else if (child instanceof RouterWrapper){
			Router node = (Router)((RouterWrapper)child).getWorkflowModelElement();
			subflow.getRouters().remove(node);
			laneShape.getWorkflowNodeShapes().remove((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getRoutersWrapper().deleteChild(child);
		}else if (child instanceof StartNodeWrapper){
			StartNode node = (StartNode)((StartNodeWrapper)child).getWorkflowModelElement();
			subflow.getStartNodes().remove(node);
			laneShape.getWorkflowNodeShapes().remove((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getStartNodesWrapper().deleteChild(child);
		}else if (child instanceof EndNodeWrapper){
			EndNode node = (EndNode)((EndNodeWrapper)child).getWorkflowModelElement();
			subflow.getEndNodes().remove(node);
			laneShape.getWorkflowNodeShapes().remove((WorkflowNodeShape)((ModelWrapper) child).getDiagramElement());
			subProcessWrapper.getEndNodesWrapper().deleteChild(child);
		}else if (child instanceof CommentWrapper){
			CommentShape elm = (CommentShape)((EndNodeWrapper)child).getDiagramElement();
			laneShape.getComments().remove(elm);
		}
		else if (child instanceof GroupWrapper){
			GroupShape elm = (GroupShape) ((GroupWrapper)child).getDiagramElement();
			laneShape.getComments().remove(elm);
		}else if (child instanceof ServiceDefWrapper){
			this.getParent().deleteChild(child);//交给SubProcessWrapper处理
		}
		
		subProcessWrapper.removeFromSnModelWrapperMap(child.getSn());
		super.deleteChild(child);
	}
	
	public String getElementType() {
		return Fpdl20DiagramElement.LANE.name();
	}
}
